<?php

declare(strict_types=1);
/**
 * This file is part of habo_new_media.
 *
 * @link     https://www.berlen.cn/
 * @contact  tech@berlen.cn
 * @license  http://gitlab.rehou.cn/habo/habo_new_media/-/blob/master/README.md
 */
namespace app\service\batch\kuaishou\schema;

use app\enum\ConfigEnum;
use app\enum\KuaiShouEnum;
use app\model\BatchCreateSchemaUriModel;
use app\model\ClientAccountModel;
use app\model\KsAdvertiserSchemaCodeModel;
use app\model\mongo\MongoKsPicModel;
use app\model\mongo\MongoKsSchemaPicModel;
use app\service\client\AccountService;
use MongoDB\BSON\Regex;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Cache;
use think\facade\Db;

/**
 * 直达链接图片服务.
 */
class SchemaPicService extends SchemaService
{
    protected const BATCH_KEY = ConfigEnum::CACHE_CONFIG[KuaiShouEnum::BATCH_CONFIG_LOCK_KEY]['schema_pic'];

    /**
     * @var batchCreateSchemaUriModel 直达链接模型
     */
    private BatchCreateSchemaUriModel $uriModel;

    /**
     * @var null|ClientAccountModel 账户信息
     */
    private ?ClientAccountModel $account;

    /**
     * @var null|MongoKsSchemaPicModel 关系模型
     */
    private ?MongoKsSchemaPicModel $schema;

    /**
     * @var null|MongoKsPicModel 图片素材模型
     */
    private ?MongoKsPicModel $picModel;

    /**
     * 运行设置视频.
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws DataNotFoundException
     */
    public function setMaterial(string $advId = '', string $objectId = ''): bool
    {
        if (! $this->setSchemaPicList($advId, $objectId)) {
            return false;
        }

        if (! $this->setSchemaPic()) {
            return false;
        }

        return true;
    }

    /**
     * 设置直达链接是否已使用.
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     * @throws \Exception
     */
    public static function setSchemaUse(): bool
    {
        $list = (new KsAdvertiserSchemaCodeModel())
            ->where('type', KuaiShouEnum::SCHEMA_PIC)
            ->limit(20)
            ->select();

        if (count($list) <= 0) {
            return self::setError('数据为空');
        }

        foreach ($list as $model) {
            $obj = (new BatchCreateSchemaUriModel())
                ->where('advertiser_id', $model->getAttr('advertiser_id'))
                ->where('app_id', $model->getAttr('app_id'))
                ->where('material_id', $model->getAttr('material_id'))
                ->where('type', KuaiShouEnum::SCHEMA_PIC)
                ->find();

            if ($obj instanceof BatchCreateSchemaUriModel && $obj->getKey() > 0) {
                $obj->setAttr('has_use', BatchCreateSchemaUriModel::USE);

                if (! $obj->save()) {
                    return self::setError('保存失败');
                }
            }

            $model->delete();
        }

        return true;
    }

    /**
     * 设置直达链接图片队列.
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function setSchemaQueue(string $advId = '', string $materialId = ''): bool
    {
        $account = AccountService::getAccountModel(0, $advId);

        if (! $account instanceof ClientAccountModel || $account->getKey() <= 0) {
            return self::setError('获取对应账户失败');
        }

        $list = (new MongoKsPicModel())
            ->where('name', new Regex('^' . $materialId, 'i'))
            ->where('account_id', $account->getKey())
            ->select();

        if (count($list) <= 0) {
            return self::setError('无数据');
        }

        $redis = Cache::store('redis')->handler();
        foreach ($list as $model) {
            $val = $advId . '|||' . $model->getAttr('_id');
            $redis->rPush(ConfigEnum::CACHE_CONFIG[KuaiShouEnum::BATCH_CONFIG_KEY]['batch_schema_pic'], $val);
        }

        return true;
    }

    /**
     * 设置图片信息.
     * @throws DbException
     */
    private function setSchemaPic(): bool
    {
        if (! self::setMaterialPicNum()) {
            return self::setError('设置素材数失败');
        }

        if (! self::setPicCoverUrl()) {
            return self::setError('更新封面ID失败');
        }

        return $this->savePicMaterial();
    }

    /**
     * 直达链接图片数据.
     * @param string $advId 账户ID
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private function setSchemaPicList(string $advId = '', string $objectId = ''): bool
    {
        $this->account = AccountService::getAccountModel(0, $advId);
        if (! $this->account instanceof ClientAccountModel || ! $this->account->getKey()) {
            return self::setError('账户数据不存在');
        }

        $this->picModel = (new MongoKsPicModel())->where('_id', $objectId)->find();

        if (! $this->picModel instanceof MongoKsPicModel || ! $this->picModel->getKey()) {
            return self::setError('数据不存在');
        }

        $photoArr = explode('-', $this->picModel->getAttr('name'));
        if (count($photoArr) <= 1) {
            return self::setError('数据不正确');
        }

        $materialId = trim($photoArr[0]);

        $this->uriModel = (new BatchCreateSchemaUriModel())
            ->where('advertiser_id', $advId)
            ->whereRaw('BINARY material_id = :material_id', ['material_id' => $materialId])
            ->where('type', KuaiShouEnum::SCHEMA_PIC)
            ->findOrEmpty();

        if (! $this->uriModel->getKey()) {
            $this->picModel->setAttr('is_material', KuaiShouEnum::PIC_MATERIAL_DISABLE);
            $this->picModel->save();

            return self::setError('物料ID不存在');
        }
        $this->picModel->setAttr('is_material', KuaiShouEnum::PIC_MATERIAL_ENABLE);
        $this->picModel->save();

        $this->schema = (new MongoKsSchemaPicModel())
            ->where('account_id', $this->account->getKey())
            ->where('material_id', $materialId)
            ->where('pic_id', $this->picModel->getAttr('pic_id'))
            ->findOrEmpty();

        if (! $this->schema->getKey()) {
            $this->schema->setAttrs([
                'client_id' => $this->account->getAttr('client_id'),
                'account_id' => $this->account->getKey(),
                'adv_id' => $this->account->getAttr('advertiser_id'),
                'material_id' => $photoArr[0],
                'pic_id' => $this->picModel->getAttr('pic_id'),
                'image_token' => $this->picModel->getAttr('image_token'),
                'version_time' => time(),
                'pic_type' => $this->picModel->getAttr('width') > $this->picModel->getAttr('height') ? KuaiShouEnum::CREATIVE_MATERIAL_TYPE_PIC_HORIZONTAL : KuaiShouEnum::CREATIVE_MATERIAL_TYPE_PIC_VERTICAL,
            ]);
        } else {
            $this->schema->setAttrs([
                'pic_type' => $this->picModel->getAttr('width') > $this->picModel->getAttr('height') ? KuaiShouEnum::CREATIVE_MATERIAL_TYPE_PIC_HORIZONTAL : KuaiShouEnum::CREATIVE_MATERIAL_TYPE_PIC_VERTICAL,
            ]);
        }

        return $this->schema->save();
    }

    /**
     * 设置图片素材数.
     * @throws DbException
     */
    private function setMaterialPicNum(): bool
    {
        $horizontalNum = Db::connect('mongodb')->name('ks_schema_pic')
            ->master()
            ->where('account_id', $this->account->getKey())
            ->where('material_id', $this->uriModel->getAttr('material_id'))
            ->where('pic_type', KuaiShouEnum::CREATIVE_MATERIAL_TYPE_PIC_HORIZONTAL)
            ->count();
        $this->uriModel->setAttr('horizontal_material_num', $horizontalNum);

        $verticalNum = Db::connect('mongodb')->name('ks_schema_pic')
            ->master()
            ->where('account_id', $this->account->getKey())
            ->where('material_id', $this->uriModel->getAttr('material_id'))
            ->where('pic_type', KuaiShouEnum::CREATIVE_MATERIAL_TYPE_PIC_VERTICAL)
            ->count();

        if ($this->schema->getAttr('pic_type') == KuaiShouEnum::CREATIVE_MATERIAL_TYPE_PIC_HORIZONTAL) {
            $horizontalNum = $horizontalNum ?: 1;
        } else {
            $verticalNum = $verticalNum ?: 1;
        }

        $this->uriModel->setAttr('vertical_material_num', $verticalNum);
        $this->uriModel->setAttr('has_material', $horizontalNum + $verticalNum);
        return true;
    }

    /**
     * 更新封面ID.
     */
    private function setPicCoverUrl(): bool
    {
        if ($this->schema instanceof MongoKsSchemaPicModel && $this->schema->getKey()) {
            if (empty($this->uriModel->getAttr('material_object_id'))) {
                $this->uriModel->setAttr('material_object_id', strval($this->picModel->getKey()));
            }
        }

        return true;
    }


    /**
     * 保存素材信息.
     * @return bool
     */
    private function savePicMaterial(): bool
    {
        (new BatchCreateSchemaUriModel())
            ->where('advertiser_id', $this->account->getAttr('advertiser_id'))
            ->where('type', KuaiShouEnum::SCHEMA_PIC)
            ->where('material_id', $this->uriModel->getAttr('material_id'))
            ->update([
                'vertical_material_num' => $this->uriModel->getAttr('vertical_material_num'),
                'horizontal_material_num' => $this->uriModel->getAttr('horizontal_material_num'),
                'has_material' => $this->uriModel->getAttr('has_material'),
                'material_object_id' => $this->uriModel->getAttr('material_object_id'),
                'update_time' => time(),
            ]);
        return true;
    }
}
